{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Map() 和 Reduce() 函数"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### map\n",
    "\n",
    "- 基本方式：接收两个参数，一个是函数，一个是Iterable （可迭代对象）\n",
    "\n",
    "- map将传入的函数依次作用到序列的每个元素，结果作为Iterator返回 （生成器对象）"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<map object at 0x00000170C1ED8610>\n",
      "[1, 4, 9, 16, 25, 36, 49, 64, 81]\n",
      "use lambda ftn\n",
      "[1, 4, 9, 16, 25, 36, 49, 64, 81]\n"
     ]
    }
   ],
   "source": [
    "# 将 a=[1,2,3,4,5,6,7,8,9] 转换为 [1*1,2*2,..., 9*9]\n",
    "\n",
    "# 列表表达式\n",
    "a=[1,2,3,4,5,6,7,8,9]\n",
    "# [i*i for i in a]\n",
    "\n",
    "# 使用map函数\n",
    "def f(x):\n",
    "    return x*x\n",
    "\n",
    "result = map(f,a)\n",
    "print(result)\n",
    "print(list(result))\n",
    "\n",
    "# 使用map + lambda\n",
    "print('use lambda ftn')\n",
    "print(list(map(lambda x: x*x, a)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "round: 1\n",
      "5\n",
      "round: 2\n",
      "4\n",
      "round: 3\n",
      "3\n",
      "round: 4\n",
      "2\n",
      "round: 5\n",
      "1\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "[None, None, None, None, None]"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 理解 map是如何运作的\n",
    "a = list('54321')\n",
    "count = 1\n",
    "def f(x):\n",
    "    global count\n",
    "    print('round:', count)\n",
    "    print(x)\n",
    "    count = count + 1\n",
    "b = map(f,a)\n",
    "list(b)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 练习：将 a 列表中每个int转换成字符串\n",
    "a=[1,2,3,4,5,6,7,8,9]\n",
    "# result=map(str, a)\n",
    "# list(result)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[(2, 1), (7, 10), (10, 21)]"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "\"\"\"\n",
    "map()可以传入多个可迭代对象，\n",
    "运行时，从每个iterable中取对应位置的元素传入进前面的函数中\n",
    "\"\"\"\n",
    "result = map(lambda x,y:(x+y,x*y), [1,2,3],[1,5,7])\n",
    "list(result)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "4325789\n"
     ]
    }
   ],
   "source": [
    "# 练习：将 a=[4,3,2,5,7,8,9]  转换为 4325789\n",
    "\n",
    "a=[4,3,2,5,7,8,9]  \n",
    "# 用join\n",
    "int(''.join(map(str,a)))\n",
    "\n",
    "# 用 for 循环\n",
    "c=0\n",
    "for i in a:\n",
    "    c=c*10+i\n",
    "print(c)  \n",
    "\n",
    "# 可以使用reduce 函数实现上述过程\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Reduce\n",
    "\n",
    "- 把一个函数（含有两个参数）作用在一个序列[x1,x2,x3]上，把结果继续和序列的下一个元素做累积计算\n",
    "\n",
    "- `reduce(f, [x1,x2,x3,x4])= f(f(f(x1,x2),x3),x4)`\n",
    "\n",
    "- 返回一个值,value "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "4325789"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from functools import reduce\n",
    "\n",
    "a=[4,3,2,5,7,8,9]  \n",
    "# def f(x,y):\n",
    "#     return 10*x+y\n",
    "\n",
    "reduce(lambda x,y:10*x+y,a)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "7257600"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 练习：计算n！\n",
    "n=5\n",
    "\n",
    "def factorial(n):\n",
    "    return 2*reduce(lambda x,y:x*y, range(1,n+1))\n",
    "\n",
    "factorial(10)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "240"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 练习：计算2*n！\n",
    "# `reduce(function, seq., initial)`\n",
    "n=5\n",
    "reduce(lambda x,y:x*y, range(1,n+1),2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "467\n"
     ]
    }
   ],
   "source": [
    "# 练习：计算所有人的年龄之和\n",
    "scientists =({'name':'Alan Turing', 'age':105, 'gender':'male'},\n",
    "             {'name':'Dennis Ritchie', 'age':76, 'gender':'male'},\n",
    "             {'name':'Ada Lovelace', 'age':202, 'gender':'female'},\n",
    "             {'name':'Frances E. Allen', 'age':84, 'gender':'female'})\n",
    "\n",
    "total_age = reduce(lambda x,y: x+y['age'], scientists,0)\n",
    "print(total_age)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'male': ['Alan Turing', 'Dennis Ritchie'],\n",
       " 'female': ['Ada Lovelace', 'Frances E. Allen']}"
      ]
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 练习：由scientists 得到 \n",
    "# {'male': ['Alan Turing', 'Dennis Ritchie'], 'female': ['Ada Lovelace', 'Frances E. Allen']}\n",
    "scientists =({'name':'Alan Turing', 'age':105, 'gender':'male'},\n",
    "             {'name':'Dennis Ritchie', 'age':76, 'gender':'male'},\n",
    "             {'name':'Ada Lovelace', 'age':202, 'gender':'female'},\n",
    "             {'name':'Frances E. Allen', 'age':84, 'gender':'female'})\n",
    "\n",
    "#x_dict={'male':[],'female':[]}\n",
    "def gender_group(x_dict,y):\n",
    "    x_dict[y['gender']].append(y['name'])\n",
    "    return x_dict\n",
    "\n",
    "result = reduce(gender_group, scientists,{'male':[],'female':[]} )\n",
    "\n",
    "#result = reduce(lambda x_dict,y:x_dict[y['gender']].append(y['name']), scientists,{'male':[],'female':[]} )\n",
    "result\n",
    "    \n",
    "\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### exercise\n",
    "\n",
    "实现  str(), int()\n",
    "\n",
    "'5632' 转化为 5632\n",
    "\n",
    "step 1: 提取字符串中每个元素，转化为数字，得到一个数字序列\n",
    "\n",
    "step 2: 通过数字序列，每两个*10相加，得到一个整数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [],
   "source": [
    "def char2int(s):\n",
    "    digits ={'0':0,'1':1, '2':2,'3':3,'4':4,'5':5,'6':6,'7':7,'8':8,'9':9}\n",
    "    return digits[s]\n",
    "\n",
    "def f(x,y):\n",
    "    return x*10+y"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "5632"
      ]
     },
     "execution_count": 36,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a='5632' \n",
    "#m=map(char2int,a)\n",
    "reduce(f,map(char2int,a))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "567890"
      ]
     },
     "execution_count": 37,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 合并为一个函数\n",
    "# 常量放在前面，常量命名用大写\n",
    "\n",
    "DIGITS ={'0':0,'1':1, '2':2,'3':3,'4':4,'5':5,'6':6,'7':7,'8':8,'9':9}\n",
    "def str2int(s):\n",
    "    def char2int(s):        \n",
    "        return DIGITS[s]\n",
    "\n",
    "    def f(x,y):\n",
    "        return x*10+y\n",
    "    \n",
    "    return reduce(f,map(char2int,s))\n",
    "\n",
    "str2int('567890')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "567890"
      ]
     },
     "execution_count": 39,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 继续优化, 使用 #lambda 表达式\n",
    "\n",
    "\n",
    "DIGITS ={'0':0,'1':1, '2':2,'3':3,'4':4,'5':5,'6':6,'7':7,'8':8,'9':9}\n",
    "def str2int(s):\n",
    "    def char2int(s):        \n",
    "        return DIGITS[s]\n",
    "\n",
    "    return reduce(lambda x,y:10*x+y,map(char2int,s))\n",
    "\n",
    "str2int('567890')"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
